#include <base/args_solve.hpp>
#include <iostream>
#include <string>

int Print(int a, double b) 
{
	std::cout << "Print: " << a << " " << b << std::endl;
	return 0; 
}

//函数对象
struct MyStruct
{
	double Fn(char, char, std::string) const { return 0; }
	char operator()(double, char*) {
		return ' ';
	}
};

void TestArgsName()
{
    using namespace reflect;
    auto t = std::make_tuple(42, 3.14, std::string("hello world"));
    std::cout << typeid(std::get<0>(t)).name() << std::endl;
    std::cout << typeid(std::get<1>(t)).name() << std::endl;
    std::cout << typeid(std::get<2>(t)).name() << std::endl;
    std::cout << Print_Type<decltype(std::get<0>(t))>() << std::endl;
    std::cout << Print_Type<decltype(std::get<1>(t))>() << std::endl;
    std::cout << Print_Type<decltype(std::get<2>(t))>() << std::endl;
}

void TestArgsSolve()
{
    using namespace reflect;
    auto fn = std::function<int(int, double)>(Print);
	std::cout << Print_Type<function_traits<decltype(fn)>::function_type>() << std::endl;
	constexpr auto nargs = function_traits<decltype(Print)>::arity;
	std::cout << Print_Type<function_traits<decltype(Print)>::function_type>() << std::endl;
	std::cout << Print_Type<function_traits<decltype(&Print)>::function_type>() << std::endl;
	std::cout << Print_Type<function_traits<MyStruct>:: function_type>() << std::endl;
	std::cout << Print_Type<function_traits<decltype(&MyStruct::Fn)>::function_type>() << std::endl;
	std::cout << "=====" << std::endl;
    std::cout << Print_Type<function_traits<decltype(&MyStruct::Fn)>::ArgN_t<0>>() << std::endl;
	std::cout << Print_Type<function_traits<decltype(&MyStruct::Fn)>::ArgN_t<1>>() << std::endl;
    std::cout << Print_Type<function_traits<decltype(&MyStruct::Fn)>::ArgN_t<2>>() << std::endl;
	std::cout << "=====" << std::endl;

	using T = decltype(&MyStruct::Fn);
	std::cout << Print_Type<T>() << std::endl;
	std::cout << Print_Type<function_traits<decltype(Print)>::Ret_type>() << std::endl;
	std::cout << Print_Type<function_traits<decltype(Print)>::function_pointer>() << std::endl;
	std::cout << Print_Type<function_traits<decltype(Print)>::ArgN_t<1>>() << std::endl;
}


void TestArgsConvert()
{
	using namespace reflect;
	std::string str0 = "1";
	std::string str1 = "2.2";
	using ArgType0 = function_traits<decltype(Print)>::ArgN_t<0>;
	using ArgType1 = function_traits<decltype(Print)>::ArgN_t<1>;
	auto arg0 = Convert_Type<ArgType0> (str0);
	auto arg1 = Convert_Type<ArgType1> (str1);
	std::cout << Print_Type<decltype(arg0)>() << std::endl;
	std::cout << Print_Type<decltype(arg1)>() << std::endl;
	Print(arg0, arg1);
}

int main()
{
    // TestArgsName();
    // TestArgsSolve();
	TestArgsConvert();
}